/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.registration.gui.security;

import it.polimi.registration.business.security.boundary.EventManager;
import it.polimi.registration.business.security.boundary.InviteManager;
import it.polimi.registration.business.security.boundary.UserManager;
import it.polimi.registration.business.security.entity.Event;
import it.polimi.registration.business.security.entity.Invite;
import it.polimi.registration.business.security.entity.InvitePK;
import it.polimi.registration.business.security.entity.User;
import java.io.IOException;
import java.io.Serializable;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
;
 
import org.primefaces.event.ScheduleEntryMoveEvent;
import org.primefaces.event.ScheduleEntryResizeEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleModel; 
import org.primefaces.event.ScheduleEntryMoveEvent;
import org.primefaces.event.ScheduleEntryResizeEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleModel;

/**
 *
 * @author Stefano
 */


@Named
@ViewScoped
public class CalendarBean implements Serializable {

    @Inject
    private EventManager em;

    @Inject
    private UserManager um;

    @Inject
    private Event e;

    @Inject
    private EventBean eb;

    @Inject
    private InviteBean ib;

    @Inject
    private WeatherBean wb;

    @Inject
    private InviteManager im;

    @Inject
    private ResearchBean rb;
    
    @Inject
    private NotificationBean nb;
    
    @Inject
    private NotificationView nw;

    private InvitePK invitePK;
    private User invitedUser;
    private int weather;
    private User searchedUser;
    private List<User> selectedUsers;
    private List<User> participants;

    private boolean searched = false;
    private boolean visible = true;
    private boolean pending=false;
    private boolean response=false;
    private boolean friend=false;

    private List<Event> eventList;
    private EventView event;
    private ScheduleModel eventModel;

    @PostConstruct
    public void init() {
        eventModel = new DefaultScheduleModel();
        eventList = eb.findAllEvent(um.getLoggedUser());
        selectedUsers = new ArrayList();
        participants = new ArrayList();        
        event = new EventView();
        if (!(eventList.isEmpty())) {
            for (Event evento : eventList) {
                event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                eventModel.addEvent(event);
                event.setId(evento.getId());
                weather = wb.weather(event.getLocation(), event.getStartDate());
                event.setWeather(wb.getWeatherDescription(weather));
                event.setEditable(true);
                event.setExistingEvent(true);
                try {                
                    wb.checkWeatherEvent(evento);
                } catch (IOException ex) {
                    Logger.getLogger(CalendarBean.class.getName()).log(Level.SEVERE, null, ex);
                }
                participants = im.findParticipants(evento);
                if(participants.isEmpty()){            
                    event.setParticipantsList("No one");
                }
                else{
                    for(User user : participants){
                        event.setParticipantsList(user.getEmail());
                    }
                }        
            }
        }
        eventList = im.findAcceptedEvents(um.getLoggedUser());
        if (!(eventList.isEmpty())) {
            for (Event evento : eventList) {
                event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                eventModel.addEvent(event);
                event.setId(evento.getId());
                weather = wb.weather(event.getLocation(), event.getStartDate());
                event.setWeather(wb.getWeatherDescription(weather));
                event.setEditable(false);
                try { 
                    wb.checkWeatherEvent(evento);
                } catch (IOException ex) {
                    Logger.getLogger(CalendarBean.class.getName()).log(Level.SEVERE, null, ex);
                }
                participants = im.findParticipants(evento);
                if(participants.isEmpty()){            
                    event.setParticipantsList("No one");
                }
                else{
                    for(User user : participants){
                        event.setParticipantsList(user.getEmail());
                    }
                }
            }
        }
 nw.ThereIsanotify();
    }

    public ScheduleModel getEventModel() {
        return eventModel;
    }

    public void onDateSelect(SelectEvent selectEvent) {
        event = new EventView("", (Date) selectEvent.getObject(), (Date) selectEvent.getObject(), "", FALSE, FALSE);
    }

    public void onEventSelect(SelectEvent selectEvent) {
        event = (EventView) selectEvent.getObject();
    }

    public void onEventMove(ScheduleEntryMoveEvent event) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Event moved", "Day delta:" + event.getDayDelta() + ", Minute delta:" + event.getMinuteDelta());
        try {
            eb.moveEvent(event.getScheduleEvent().getId(), event.getDayDelta(), event.getMinuteDelta());
        } catch (IOException ex) {
            Logger.getLogger(CalendarBean.class.getName()).log(Level.SEVERE, null, ex);
        }
        addMessage(message);
    }

    public void onEventResize(ScheduleEntryResizeEvent event) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Event resized", "Day delta:" + event.getDayDelta() + ", Minute delta:" + event.getMinuteDelta());
        eb.resizeEvent(event.getScheduleEvent().getId(), event.getDayDelta(), event.getMinuteDelta());
        addMessage(message);
    }

    private void addMessage(FacesMessage message) {
        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public EventView getEvent() {
        return event;
    }

    public void setEvent(EventView event) {
        this.event = event;
    }

    public void addEvent(ActionEvent actionEvent) {
        if (event.getId() == null) {
            eventModel.addEvent(event);
            e.setId(event.getId());
            weather = wb.weather(event.getLocation(), event.getStartDate());
            event.setWeather(wb.getWeatherDescription(weather));
            e.setTitle(event.getTitle());
            Calendar startDate = Calendar.getInstance();
            startDate.setTime(event.getStartDate());
            e.setStartTime(startDate);
            Calendar endDate = Calendar.getInstance();
            endDate.setTime(event.getEndDate());
            endDate.add(Calendar.MINUTE, 120);
            e.setEndTime(endDate);
            e.setLocation(event.getLocation());
            e.setOutdoor(event.getOutdoor());
            e.setVisibility(event.getVisibility());
            e.setWeatherCondition(weather);
            em.save(e);
            try {
                wb.checkWeatherEvent(e);
            } catch (IOException ex) {
                Logger.getLogger(CalendarBean.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (selectedUsers != null) {
                if (!selectedUsers.isEmpty()) {
                    event.setExistingEvent(true);
                    for (User user : selectedUsers) {
                        invitePK = new InvitePK(user.getEmail(), e.getId());
                        Invite i = new Invite(invitePK);
                        i.setEvent(e);
                        i.setUser(user);
                        im.save(i);
                    }
                }
            }
 
        } else {
            Event oldEvent = em.getEvent(event.getId());
            String oldTitle = oldEvent.getTitle();
            String oldLocation = oldEvent.getLocation();
            Calendar oldStart = oldEvent.getStartTime();
            Calendar oldEnd = oldEvent.getEndTime();
            Boolean oldOutdoor = oldEvent.getOutdoor();
            if (um.getLoggedUser().getEmail().equals(oldEvent.getCreator().getEmail())) {
                weather = wb.weather(event.getLocation(), event.getStartDate());
                event.setWeather(wb.getWeatherDescription(weather));
                event.setEditable(true);
                oldEvent.setTitle(event.getTitle());
                Calendar startDate = Calendar.getInstance();
                startDate.setTime(event.getStartDate());
                oldEvent.setStartTime(startDate);
                Calendar endDate = Calendar.getInstance();
                endDate.add(Calendar.MINUTE, 120);
                endDate.setTime(event.getEndDate());
                oldEvent.setEndTime(endDate);
                oldEvent.setLocation(event.getLocation());
                oldEvent.setOutdoor(event.getOutdoor());
                oldEvent.setVisibility(event.getVisibility());
                oldEvent.setWeatherCondition(weather);
                em.update(oldEvent);
                try {
                    wb.checkWeatherEvent(oldEvent);
                } catch (IOException ex) {
                    Logger.getLogger(CalendarBean.class.getName()).log(Level.SEVERE, null, ex);
                }
                eventModel.updateEvent(event);
                participants = im.findInvited(oldEvent);
                if (participants != null) {
                    if (!participants.isEmpty()) {
                        if (!event.getTitle().equals(oldTitle)
                                || !event.getLocation().equals(oldLocation)
                                || !event.getStartDate().equals(oldStart.getTime())
                                || !event.getEndDate().equals(oldEnd.getTime())
                                || !(Objects.equals(event.getOutdoor(), oldOutdoor))) {
                            for (User user : participants) {
                                List<Invite> invites = im.findInvites(user, oldEvent);
                                for (Invite invite : invites) {
                                    im.delete(invite);
                                }
                                invitePK = new InvitePK(user.getEmail(), oldEvent.getId());
                                Invite i = new Invite(invitePK);
                                i.setEvent(oldEvent);
                                i.setUser(user);
                                im.save(i);
                            }
                        }
                    }
                }
            }
        }
        event = new EventView();
    }

    public void deleteEvent(ActionEvent actionEvent) {
        eventModel.deleteEvent(event);
        Event e = em.getEvent(event.getId());
        Event emerge = em.merge(e);
        em.delete(emerge);

        event = new EventView();
    }
    
    public void accetta()
    {
        getRelationship(this.searchedUser);
        nb.accetta(this.searchedUser);
    }
    
    public void rifiuta()
    {
        getRelationship(this.searchedUser);
        nb.rifiuta(this.searchedUser);
    }
    
    public void sendRequest()
    {
        getRelationship(this.searchedUser);
        nb.sendRequest(this.searchedUser);
    }
    
      
    public void getRelationship(User user)
    {
        int response1,response2;
        response1=um.Relationshipcheck(um.getLoggedUser(),user);
        response2=um.Relationshipcheck(user,um.getLoggedUser());
        if(response1==0)
        {
            this.pending=FALSE;
        }
        else if(response1==1)
        {
            this.pending=TRUE;
        }
        if(response2==0)
        {
            this.response=FALSE;
        }
        else if(response2==1)
        {
            this.response=TRUE;
        }
        
        this.friend=um.isFriend(this.searchedUser);
    }
    
    

    public void search() {
        this.searchedUser = rb.research();
        searched = true;
        visible = true;
        getRelationship(this.searchedUser);
        eventModel = new DefaultScheduleModel();
        if (searchedUser.getCalendarVisibility()) {
            eventList = eb.findAllEvent(searchedUser);
            if (!(eventList.isEmpty())) {
                for (Event evento : eventList) {
                    event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                    eventModel.addEvent(event);
                    event.setId(evento.getId());
                    weather = wb.weather(event.getLocation(), event.getStartDate());
                    event.setWeather(wb.getWeatherDescription(weather));
                    event.setEditable(true);
                    event.setExistingEvent(true);
                    participants = im.findParticipants(evento);
                    if(participants.isEmpty()){            
                        event.setParticipantsList("No one");
                    }
                    else{
                        for(User user : participants){
                            event.setParticipantsList(user.getEmail());
                        }
                    }  

                }
            }

            eventList = im.findAcceptedEvents(searchedUser);
            if (!(eventList.isEmpty())) {
                for (Event evento : eventList) {
                    event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                    eventModel.addEvent(event);
                    event.setId(evento.getId());
                    weather = wb.weather(event.getLocation(), event.getStartDate());
                    event.setWeather(wb.getWeatherDescription(weather));
                    event.setEditable(false);
                    participants = im.findParticipants(evento);
                    if(participants.isEmpty()){            
                        event.setParticipantsList("No one");
                    }
                    else{
                        for(User user : participants){
                            event.setParticipantsList(user.getEmail());
                        }
                    }  
                }
            }
        }
        event = null;
    }

    public void resetSearch() {
        this.searched = false;
        eventModel = new DefaultScheduleModel();
        eventList = eb.findAllEvent(um.getLoggedUser());
        if (!(eventList.isEmpty())) {
            for (Event evento : eventList) {
                event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                eventModel.addEvent(event);
                event.setId(evento.getId());
                weather = wb.weather(event.getLocation(), event.getStartDate());
                event.setWeather(wb.getWeatherDescription(weather));
                event.setEditable(true);
                event.setExistingEvent(true);
                participants = im.findParticipants(evento);
                if(participants.isEmpty()){            
                    event.setParticipantsList("No one");
                }
                else{
                    for(User user : participants){
                        event.setParticipantsList(user.getEmail());
                    }
                }  
            }
        }
        eventList = im.findAcceptedEvents(um.getLoggedUser());
        if (!(eventList.isEmpty())) {
            for (Event evento : eventList) {
                event = new EventView(evento.getTitle(), evento.getStartTime().getTime(), evento.getEndTime().getTime(), evento.getLocation(), evento.getVisibility(), evento.getOutdoor());
                eventModel.addEvent(event);
                event.setId(evento.getId());
                weather = wb.weather(event.getLocation(), event.getStartDate());
                event.setWeather(wb.getWeatherDescription(weather));
                event.setEditable(false);
                participants = im.findParticipants(evento);
                if(participants.isEmpty()){            
                    event.setParticipantsList("No one");
                }
                else{
                    for(User user : participants){
                        event.setParticipantsList(user.getEmail());
                    }
                }  
            }
        }

    }
    
       
    public boolean getPending(){return this.pending;}
    public boolean getResponse(){return this.response;}
    public boolean getFriend(){return this.friend;}


    public boolean getSearched() {
        return searched;
    }

    public User getSearchedUser() {
        return searchedUser;
    }

    public boolean getVisible() {
        return visible;
    }

    public User getInvitedUser() {
        if (invitedUser == null) {
            invitedUser = new User();
        }
        return invitedUser;
    }

    public List<User> getSelectedUsers() {
        return selectedUsers;
    }

    public void setSelectedUsers(List<User> selectedUser) {
        this.selectedUsers = selectedUser;
    }

    public List<User> complete(String query) {
        List<User> allUsers = um.findAllUser();
        List<User> filteredUsers = new ArrayList<User>();

        for (int i = 0; i < allUsers.size(); i++) {
            User skin = allUsers.get(i);
            if (skin.getEmail().contains(query)) {
                filteredUsers.add(skin);
            }
        }

        return filteredUsers;
    }

    public List<User> getParticipants() {
        return participants;
    }
    

    

}
